package io.github.uicdb.badskill;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.concurrent.CompletableFuture;

public abstract class SkillPageDataProvider implements DataProvider {
    protected final DataGenerator generator;
    protected final PackOutput.PathProvider pageProvider;
    protected final PackOutput packOutput;
    protected final String modid;


    public SkillPageDataProvider(DataGenerator generator, String modid, boolean outToTest) {
        this.generator = generator;
        this.modid = modid;
        this.packOutput = outToTest ? getPackOutputTest(generator.getPackOutput()) : generator.getPackOutput();
        pageProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "skill_page");
    }

    public CompletableFuture<?> save(SkillPage page, CachedOutput output) {
        return DataProvider.saveStable(output, page.toJson(), pageProvider.json(page.id));
    }
    public Builder add(String page){
        return new Builder(new ResourceLocation(modid,page));
    }
    protected PackOutput getPackOutputTest(PackOutput from) {
        return new PackOutput(from.getOutputFolder().getParent().getParent().resolve("test").resolve("resources"));
    }

    @Override
    public @NotNull CompletableFuture<?> run(@NotNull CachedOutput cachedOutput) {
        return CompletableFuture.allOf(generate(cachedOutput).toArray(new CompletableFuture[0]));
    }

    protected abstract List<CompletableFuture<?>> generate(@NotNull CachedOutput output);

    @Override
    public String getName() {
        return getClass().getSimpleName();
    }

    @RequiredArgsConstructor
    public final static class Builder {
        @Getter
        private final ResourceLocation page;
        private ResourceLocation background;
        private ResourceLocation icon;
        private final Map<ResourceLocation, SkillPage.Location> locations=new HashMap<>();
        private final List<SkillPage.ImageLocation> imageLocations=new ArrayList<>();
        public Builder icon(String name, String path) {
            icon = new ResourceLocation(name, path + ".png");
            return this;
        }

        public Builder background(String name, String path) {
            background = new ResourceLocation(name, path + ".png");
            return this;
        }
        public Builder image(ResourceLocation path,int x,int y,int w,int h){
            imageLocations.add(new SkillPage.ImageLocation(path,x,y,w,h));
            return this;
        }
        public Builder location(SkillOption option, int x, int y,int size ,ResourceLocation icon,ResourceLocation learned, SkillOption... parents) {
            SkillPage.Location location = SkillPage.Location.create(x, y,size,size, icon, learned,Arrays.stream(parents).map(SkillOption::getId).toArray(ResourceLocation[]::new));
            locations.put(option.getId(), location);
            return this;
        }

        public Builder location(ResourceLocation option, int x, int y,int size, ResourceLocation icon,ResourceLocation learned, ResourceLocation... parents) {
            SkillPage.Location location = SkillPage.Location.create(x, y,size,size, icon,learned, parents);
            locations.put(option, location);
            return this;
        }

        public Builder location(ResourceLocation option, int x, int y, ResourceLocation... parents) {
            return this.location(option, x, y, 16,null,null, parents);
        }

        public Builder location(SkillOption option, int x, int y, SkillOption... parents) {
            return this.location(option, x, y,16 ,null,null, parents);
        }

        public SkillPage build() {
            return new SkillPage.SkillPageBuilder().id(page).background(background).icon(icon).imageLocations(imageLocations).locations(locations).build();
        }
    }
}
